#include <gtkmm/builder.h>
#include <giomm/memoryinputstream.h>
#include <gtkmm/filechooserdialog.h>
#include <glibmm/miscutils.h>
#include <glibmm/datetime.h>
#include <giomm/file.h>
#include <giomm/fileoutputstream.h>

#include "ModuleInfomation.h"
#include "Global.h"
#include "ServiceConnection.h"
#include "ServiceInfomation.h"
#include "App.h"
#include "ServiceManager.h"
#include "Mainwin.h"

namespace Gnodroid {

    ModuleInfomation::ModuleInfomation() :
        Glib::ObjectBase("gnd_module_infomation"),
        Module(MODULE_INFOMATION)
    {
        pov_screencap_interval = std::shared_ptr<Gtk::Popover>(new Gtk::Popover());
        scl_screencap_interval = std::shared_ptr<Gtk::Scale>(new Gtk::Scale());
        m_interval = 2000;
    }

    void
    ModuleInfomation::start()
    {
        ServiceManager* serviceManager = App
                ::getCurrentApp()
                ->getServiceManager();
        ServiceConnection* serviceConnection = static_cast<ServiceConnection*>(serviceManager->getService(SERVICE_CONNECTION));
        ServiceInfomation* serviceInfomation = static_cast<ServiceInfomation*>(serviceManager->getService(SERVICE_INFOMATION));

        //get widget
        auto builder = App::getCurrentApp()
                ->getMainwin()
                ->getBuilder();

        builder->get_widget("lb_model", lb_model);
        builder->get_widget("lb_brand", lb_brand);
        builder->get_widget("lb_sdk", lb_sdk);
        builder->get_widget("lb_androidver", lb_androidver);
        builder->get_widget("lb_kernel", lb_kernel);
        builder->get_widget("lb_ram", lb_ram);
        builder->get_widget("lb_resolution", lb_resolution);

        builder->get_widget("img_screencap", img_screencap);
        builder->get_widget("btn_screencap_start", btn_screencap_start);
        builder->get_widget("btn_screencap_save", btn_screencap_save);
        builder->get_widget("mbtn_screencap_setting", mbtn_screencap_setting);

        //pov_screencap_interval = new Gtk::Popover(*mbtn_screencap_setting);
        //scl_screencap_interval = new Gtk::Scale();
        //pov_screencap_interval->set_
        pov_screencap_interval->add(*scl_screencap_interval);
        scl_screencap_interval->show();
        scl_screencap_interval->set_range(0, 5);
        scl_screencap_interval->set_value(2);
        scl_screencap_interval->property_width_request().set_value(150);
        scl_screencap_interval->set_value_pos(Gtk::POS_RIGHT);

        mbtn_screencap_setting->set_popover(*pov_screencap_interval);

        //================
        //device prop init
        serviceConnection->signal_connected().connect([this, serviceInfomation](std::string id){
            m_bIsConnected = true;
            serviceInfomation->getDeviceProp([this](bool result, std::shared_ptr<DeviceProp> prop) {
                if (result) {
                    if (m_bIsConnected) {
                        //display device prop
                        LOG(prop->toString());
                        lb_model->set_text(prop->model);
                        lb_brand->set_text(prop->brand);
                        lb_sdk->set_text(prop->sdk);
                        lb_androidver->set_text(prop->android_ver);
                        lb_kernel->set_text(prop->kernel);
                        lb_ram->set_text(std::to_string(prop->ram));
                        lb_resolution->set_text(std::to_string(prop->sc_width) + " * " + std::to_string(prop->sc_height));
                    } else {
                        LOG_ERROR("get prop but not connected");
                    }

                } else
                {
                    LOG_ERROR("get prop error");
                }
            });
        });

        serviceConnection->signal_disconnected().connect([this](std::string id){
            m_bIsConnected = false;
            __setNotConnected();
        });

        //default status is disconnected
        __setNotConnected();


        //=================
        //screencap init
        /*
        serviceConnection->signal_connected().connect([this, serviceConnection, serviceInfomation](std::string id){
            m_shrIsContinue = std::shared_ptr<bool>(new bool(true));
            m_shrInterval = std::shared_ptr<int>(new int(1000));
            serviceInfomation->getScreenCap(m_shrIsContinue, m_shrInterval,
                                            [this](bool res, Glib::RefPtr<Gio::MemoryInputStream> memInputStream) {

                if (res) {
                    LOG("get data");
                    //LOG(memInputStream->);
                    auto pixbuf = Gdk::Pixbuf::create_from_stream(memInputStream);
                    //img_screencap->clear();
                    pixbuf = pixbuf->scale_simple(350, 620, Gdk::INTERP_BILINEAR);
                    img_screencap->set(pixbuf);
                    LOG("screen seted");
                } else {
                    LOG("stop screencap");
                }

            });

        });
        serviceConnection->signal_disconnected().connect([this](std::string id){
            *m_shrIsContinue = false;
        });
        */

        //开始截图按钮被按下
        btn_screencap_start->signal_clicked().connect([this, serviceInfomation](){
            if (!m_bIsScreencapStart) {
                //当前未开始状态
                if (!m_bIsConnected) {
                    return;     //当前未跟设备连接时直接返回
                }
                m_shrIsContinue = std::shared_ptr<bool>(new bool(true));
                m_shrInterval = std::shared_ptr<int>(new int(m_interval));

                m_bIsScreencapStart = true;

                btn_screencap_start->set_image_from_icon_name("media-playback-stop-symbolic");
                //开始获取截图
                serviceInfomation->getScreenCap(m_shrIsContinue, m_shrInterval,
                                                [this](bool res, Glib::RefPtr<Gio::MemoryInputStream> memInputStream) {

                    if (!m_bIsScreencapStart) {
                        return;     //在停止截图后防止再返回
                    }
                    if (res) {
                        LOG("get data");
                        m_curScreencap = memInputStream;
                        //LOG(memInputStream->);
                        auto pixbuf = Gdk::Pixbuf::create_from_stream(memInputStream);
                        //img_screencap->clear();
                        pixbuf = pixbuf->scale_simple(350, 620, Gdk::INTERP_BILINEAR);
                        img_screencap->set(pixbuf);
                        //LOG("screen seted");
                    } else {
                        LOG("stop screencap");
                        __setStopScreencap();
                        //LOG("stop screencap");
                    }

                });
            } else {
                __setStopScreencap();
            }
        });

        //由于获取截图的线程会检测截图状态，断开时自动返回失败的截图，然后自动断开，所以这步
        //不是很必要
        serviceConnection->signal_disconnected().connect([this](std::string id) {
            if (m_bIsScreencapStart) {
                __setStopScreencap();
            }
        });

        btn_screencap_save->signal_clicked().connect([this](){
            if (m_curScreencap) {

                Mainwin* mainwin = App::getCurrentApp()
                        ->getMainwin();
                Gtk::FileChooserDialog fileChooser(*mainwin,
                                                   "保存截图",
                                                   Gtk::FILE_CHOOSER_ACTION_SAVE);
                fileChooser.set_current_folder(Glib::get_home_dir());

                Glib::DateTime data = Glib::DateTime::create_now_local();
                fileChooser.set_current_name("gnodroid" + data.format("%F.%k-%M-%S") + ".png");
                fileChooser.add_button("取消", 1);
                fileChooser.add_button("保存", 2);

                int resp = fileChooser.run();
                //fileChooser.present();

                if (resp != 2) {
                    return;
                }
                std::string fileName = fileChooser.get_filename();
                if (fileName == "") {
                    LOG("not select a file");
                    return;
                }
                LOG("save screencap to " + fileName);
                auto file = Gio::File::create_for_path(fileName);
                auto fileOS = file->replace();
                m_curScreencap->seek(0, Glib::SEEK_TYPE_SET);
                gssize dataSize = 0;
                char buff[1024 * 10];

                while (dataSize = m_curScreencap->read(buff, 1024 * 10)) {
                    fileOS->write(buff, dataSize);
                }
                fileOS->close();
            }
        });

        //当间隔改变时实时改变截图间隔
        scl_screencap_interval->signal_value_changed().connect([this](){
            double v = scl_screencap_interval->get_value();
            if (!v) {
                v = 0.001;
            }
            m_interval = int(v * 1000);
            if (m_bIsScreencapStart) {
                *m_shrInterval = m_interval;
            }
            LOG("interval change to " + std::to_string(m_interval));
        });
    }

    void
    ModuleInfomation::stop()
    {}

    void
    ModuleInfomation::__setNotConnected()
    {
        lb_model->set_text("未连接");
        lb_brand->set_text("未连接");
        lb_sdk->set_text("未连接");
        lb_androidver->set_text("未连接");
        lb_kernel->set_text("未连接");
        lb_ram->set_text("未连接");
        lb_resolution->set_text("未连接");

    }

    void
    ModuleInfomation::__setStopScreencap()
    {

        if (!m_bIsScreencapStart) {
            return;
        }

        m_bIsScreencapStart = false;
        btn_screencap_start->set_image_from_icon_name("media-playback-start-symbolic");

        *m_shrIsContinue = false;
        *m_shrInterval = 1;
    }

}
